package com.example.security.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl;
import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;

import javax.sql.DataSource;

@Configuration
public class SecurityConfigTest extends WebSecurityConfigurerAdapter {

    @Autowired
    private UserDetailsService userDetailsService;

    @Autowired
    private DataSource dataSource; //注入数据源
    //配置对象
    @Bean
    PersistentTokenRepository persistentTokenRepository(){
        JdbcTokenRepositoryImpl jdbcTokenRepositoryImpl = new JdbcTokenRepositoryImpl();
        jdbcTokenRepositoryImpl.setDataSource(dataSource);
        //在启动时自动创建表
        //jdbcTokenRepositoryImpl.setCreateTableOnStartup(true);
        return jdbcTokenRepositoryImpl;
    }

    //Web权限方案三(常用): 自定义实现类设置
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService) //指定使用哪个userDetailService实现类
                .passwordEncoder(password());
    }

    //在加密密码的过程中,需要用到PasswordEncoder接口,所以需要创建
    @Bean
    PasswordEncoder password() {
        return new BCryptPasswordEncoder();
    }

    //自定义用户登录界面
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        //用户注销
        http.logout()
                .logoutUrl("/logout") //退出的路径
                .logoutSuccessUrl("/test/hello") //退出后跳转的地址
                .permitAll();

        //配置没有权限访问跳转自定义页面
        http.exceptionHandling().accessDeniedPage("/unauth.html");

        http.formLogin() //自定义登录页面
                .loginPage("/login.html") //登录页面设置
                .loginProcessingUrl("/user/login") //登录访问路径
                .defaultSuccessUrl("/success.html")
                .permitAll() //登录成功后,跳转的路径(.defaultSuccessUrl("/test/index"))
                .and().authorizeRequests() //哪些url被保护,哪些不被保护
                .antMatchers("/","/test/hello","/user/login").permitAll() //访问这些路径时,不需要认证
                 //当前登录用户,只有具有admin权限才可以访问这个路径
                //hasAuthority(): 如果当前的主体具有指定的权限(只针对一个权限操作),则返回 true,否则返回 false
                //.antMatchers("/test/index").hasAuthority("admin")

                //访问该路径,只需要多个权限中的一个即可
                //hasAnyAuthority():如果当前的主体有任何提供的角色(给定的作为一个逗号分隔的字符串列表)的话,返回true
                //.antMatchers("/test/index").hasAnyAuthority("admin","manager")

                //当前登录用户,只有是sale角色才可以访问这个路径
                //hasRole(): 如果当前主体具有指定的角色,则返回 true
                //.antMatchers("/test/index").hasRole("sale")

                //hasAnyRole(): 用户具备任何一个角色都可以访问
                .antMatchers("/test/index").hasAnyRole("sale")

                .anyRequest().authenticated()

                //记住我自动登录
                .and().rememberMe().tokenRepository(persistentTokenRepository())
                //自动登录的有效时长(秒)
                .tokenValiditySeconds(60)
                .userDetailsService(userDetailsService)

                .and().csrf().disable(); //关闭csrf防护
    }
}
